﻿using BluetoothMachine.GlobalStatics;
using BluetoothMachine.Lucifer;
using log4net;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace BluetoothMachine.Domains
{
    public class TaskManagers
    {
        private ConcurrentDictionary<string, object> _taskQueue = new ConcurrentDictionary<string, object>();
        private static readonly IDictionary<object, object> handlers = new Dictionary<object, object>();
        private static readonly object _obj = new object();
        private static TaskManagers _taskManagers = null;
        public static TaskManagers GetObject
        {
            get
            {
                if (_taskManagers == null)
                {
                    lock (_obj)
                    {
                        if (_taskManagers == null) _taskManagers = new TaskManagers();
                    }
                }
                return _taskManagers;
            }
        }

        private TaskManagers()
        {
            var types = Assembly.GetExecutingAssembly().GetTypes();
            var handlerTypes = types.Where(t => t.IsClass && t.GetInterface("IBusiness`1") != null).ToList();
            foreach (var handlerType in handlerTypes)
            {
                MethodInfo method = handlerType.GetMethod("Handle");
                var pars = method.GetParameters();
                Type entityType = pars[0].ParameterType;
                var ps = handlerType.GetConstructors()[^1].GetParameters();
                List<object> plist = new List<object>();
                foreach (var p in ps)
                {
                    plist.Add(ServiceDiscovery.ResolveSingleton(p.ParameterType));
                }
                var handler = Activator.CreateInstance(handlerType, plist.ToArray());
                handlers.Add(entityType, handler);
            }
        }
        private ILog log = log4net.LogManager.GetLogger("message");
        /// <summary>
        /// 发布
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="serviceEvent"></param>
        public void Publish<T>(T serviceEvent) where T : IDataContext
        {
            var model = ServiceDiscovery.ResolveSingleton<HomeGlobal>();
            Type eventType = serviceEvent.GetType();
            if (!handlers.ContainsKey(eventType)) return;
            string str = $"{serviceEvent.RCCX}{serviceEvent.RCCY}{serviceEvent.RCCZ}";
            if (_taskQueue.ContainsKey(str) & !_taskQueue.TryAdd(str, serviceEvent)) return;
            log.Info($"任务 {str} 触发");
            MethodInfo method = handlers[eventType].GetType().GetMethod("Handle");
            Task.Run(new Action(() => method?.Invoke(handlers[eventType], new object[] { serviceEvent })), model.ScramToken.Token);
        }

        /// <summary>
        /// 尝试移除Key
        /// </summary>
        public void RemoveKey<T>(T serviceEvent) where T : IDataContext
        {
            string str = $"{serviceEvent.RCCX}{serviceEvent.RCCY}{serviceEvent.RCCZ}";
            if (!_taskQueue.TryRemove(str, out _)) log.Error($"移除键值对失败");
        }
    }
}
